package wlt.xxljob.service.impl;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import wlt.xxljob.config.XxlJobAdmin;
import wlt.xxljob.exception.AppException;
import wlt.xxljob.service.JobInfoService;
import wlt.xxljob.util.CronExpression;
import wlt.xxljob.util.OkhttpUtil;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class JobInfoServiceImpl implements JobInfoService {
    @Autowired
    private XxlJobAdmin xxlJobAdmin;

    private String JOB_ADD = "/jobinfo/add";
    private String JOB_UPDATE = "/jobinfo/update";
    private String JOB_REMOVE = "/jobinfo/remove";
    private String JOB_LIST = "/jobinfo/pageList";

    private String SCHEDULE_TYPE_CRON = "CRON";
    private String SCHEDULE_TYPE_FIX_RATE = "FIX_RATE";

    @Override
    public int add(String jobDesc, String jobCron, String executorParam) {
        if (!CronExpression.isValidExpression(jobCron)) {
            log.warn("jobCron is invalid, jobCron={}", jobCron);
            throw new AppException("jobCron is invalid");
        }
        return add(jobDesc, SCHEDULE_TYPE_CRON, jobCron, executorParam);
    }

    @Override
    public void update(String id, String jobDesc, String jobCron, String executorParam) {
        if (!CronExpression.isValidExpression(jobCron)) {
            log.warn("jobCron is invalid, jobCron={}", jobCron);
            throw new AppException("jobCron is invalid");
        }
        update(id, jobDesc, SCHEDULE_TYPE_CRON, jobCron, executorParam);
    }

    @Override
    public int add(String jobDesc, int seconds, String executorParam) {
        if (seconds < 0) {
            log.warn("seconds is invalid, seconds={}", seconds);
            throw new AppException("seconds is invalid");
        }
        return add(jobDesc, SCHEDULE_TYPE_FIX_RATE, seconds+"", executorParam);
    }

    @Override
    public void update(String id, String jobDesc, int seconds, String executorParam) {
        if (seconds < 0) {
            log.warn("seconds is invalid, seconds={}", seconds);
            throw new AppException("seconds is invalid");
        }
        update(id,jobDesc,SCHEDULE_TYPE_FIX_RATE,seconds+"",executorParam);
    }

    @Override
    public int add(String jobDesc, String scheduleType, String scheduleConf, String executorParam) {
        /**
         *  private int jobGroup;		// 执行器主键ID
         * 	private String jobDesc;
         *
         * 	private Date addTime;
         * 	private Date updateTime;
         *
         * 	private String author;		// 负责人
         * 	private String alarmEmail;	// 报警邮件
         *
         *  private String scheduleType;			// 调度类型
         * 	private String scheduleConf;			// 调度配置，值含义取决于调度类型
         * 	private String misfireStrategy;			// 调度过期策略
         *
         * 	private String executorRouteStrategy;	// 执行器路由策略
         * 	private String executorHandler;		    // 执行器，任务Handler名称
         * 	private String executorParam;		    // 执行器，任务参数
         * 	private String executorBlockStrategy;	// 阻塞处理策略
         * 	private int executorTimeout;     		// 任务执行超时时间，单位秒
         * 	private int executorFailRetryCount;		// 失败重试次数
         *
         * 	private String glueType;		// GLUE类型
         */
        HashMap<String, String> info = new HashMap<>();
        //基础配置
        info.put("jobGroup", xxlJobAdmin.getJobGroupStr());
        info.put("jobDesc", jobDesc);
        info.put("author", xxlJobAdmin.getAuthor());
        info.put("alarmEmail", xxlJobAdmin.getAlarmEmail());
        //调度配置
        info.put("scheduleType", scheduleType);
        info.put("scheduleConf", scheduleConf);
        //任务配置
        info.put("glueType", "BEAN");
        info.put("executorHandler", xxlJobAdmin.getExecutorHandler());
        info.put("executorParam", executorParam);
        //高级配置
        info.put("misfireStrategy", "DO_NOTHING");
        info.put("executorRouteStrategy", "FIRST");
        info.put("executorBlockStrategy", xxlJobAdmin.getExecutorBlockStrategy());
        info.put("executorTimeout", xxlJobAdmin.getExecutorTimeout() + "");
        info.put("executorFailRetryCount", xxlJobAdmin.getExecutorFailRetryCount() + "");
        info.put("childJobId", "");
        info.put("triggerStatus", xxlJobAdmin.getTriggerStatusStr());

        JSONObject result = OkhttpUtil.doPost(xxlJobAdmin.getUrl() + JOB_ADD, info, cookieHeader());
        if (result.getInteger("code") == 200) {
            return Integer.parseInt(result.getString("content"));
        } else {
            log.warn(result.toJSONString());
            throw new AppException("add job failed");
        }
    }

    @Override
    public void update(String id, String jobDesc, String scheduleType, String scheduleConf, String executorParam) {
        /**
         * 运行模式（glueType）不能改
         */
        HashMap<String, String> info = new HashMap<>();
        //基础配置
        info.put("id", id);
        info.put("jobGroup", xxlJobAdmin.getJobGroupStr());
        info.put("jobDesc", jobDesc);
        info.put("author", xxlJobAdmin.getAuthor());
        info.put("alarmEmail", xxlJobAdmin.getAlarmEmail());
        //调度配置
        info.put("scheduleType", scheduleType);
        info.put("scheduleConf", scheduleConf);
        //任务配置
        info.put("executorHandler", xxlJobAdmin.getExecutorHandler());
        info.put("executorParam", executorParam);
        //高级配置
        info.put("misfireStrategy", "DO_NOTHING");
        info.put("executorRouteStrategy", "FIRST");
        info.put("executorBlockStrategy", xxlJobAdmin.getExecutorBlockStrategy());
        info.put("executorTimeout", xxlJobAdmin.getExecutorTimeout() + "");
        info.put("executorFailRetryCount", xxlJobAdmin.getExecutorFailRetryCount() + "");

        JSONObject result = OkhttpUtil.doPost(xxlJobAdmin.getUrl() + JOB_UPDATE, info, cookieHeader());
        if (result.getInteger("code") == 200) {
            log.info("update job success");
        } else {
            log.warn(result.toJSONString());
            throw new AppException("update job failed");
        }
    }

    @Override
    public void remove(int id) {
        try {
            OkhttpUtil.doGet(xxlJobAdmin.getUrl() + JOB_REMOVE + "?id=" + id, cookieHeader());
        } catch (Exception e) {
            log.warn("remove job failed, e={}", e.toString());
            throw new AppException("remove job failed");
        }
    }

    @Override
    public void select(String jobDesc) {
        HashMap<String, String> params = new HashMap<>();
        params.put("jobDesc", jobDesc);
        params.put("jobGroup", xxlJobAdmin.getJobGroupStr());
        params.put("triggerStatus", "-1");
        JSONObject result = OkhttpUtil.doPost(xxlJobAdmin.getUrl() + JOB_LIST, params, cookieHeader());
        log.info("recordsTotal:" + result.getInteger("recordsTotal"));
        if (result.getInteger("recordsTotal") > 0) {
            log.info("select job success");
        } else {
            log.warn(result.toJSONString());
            throw new AppException("select job failed");
        }
    }

    private Map<String, String> cookieHeader() {
        HashMap<String, String> headers = new HashMap<>();
        headers.put("Cookie", xxlJobAdmin.getCookie());
        return headers;
    }
}
